"""
测试夹具配置模块

提供Pytest测试框架的夹具函数，用于测试用例的前置和后置处理。
包括浏览器驱动初始化、测试数据准备等功能。
"""

import pytest
import os
from selenium import webdriver
from selenium.webdriver.chrome.options import Options as ChromeOptions
from selenium.webdriver.firefox.options import Options as FirefoxOptions
from common.read_cfg import web_cfg as read_cfg
from common.read_json import ReadJson
from utils.logger import log


class BaseDriver:
    """
    浏览器驱动基类
    负责初始化不同类型的浏览器驱动
    """
    
    @staticmethod
    def get_driver(browser_type="chrome", headless=False):
        """
        获取浏览器驱动
        :param browser_type: 浏览器类型，支持chrome、firefox等
        :param headless: 是否启用无头模式
        :return: WebDriver实例
        """
        if browser_type.lower() == "chrome":
            options = ChromeOptions()
            if headless:
                options.add_argument('--headless')
                options.add_argument('--disable-gpu')
                options.add_argument('--window-size=1920,1080')
            options.add_argument('--start-maximized')
            options.add_argument('--disable-extensions')
            options.add_argument('--ignore-certificate-errors')
            driver = webdriver.Chrome(options=options)
        elif browser_type.lower() == "firefox":
            options = FirefoxOptions()
            if headless:
                options.add_argument('--headless')
                options.add_argument('--window-size=1920,1080')
            driver = webdriver.Firefox(options=options)
        else:
            raise ValueError(f"不支持的浏览器类型: {browser_type}")
        return driver


@pytest.fixture(scope="session")
def browser():
    """
    会话级别的浏览器驱动夹具
    在整个测试会话期间只初始化一次浏览器
    """
    # 使用导入的read_cfg实例，无需重新创建
    browser_type = read_cfg.get_browser()
    headless = read_cfg.get_headless()
    
    log.info(f"开始初始化浏览器: {browser_type}, 无头模式: {headless}")
    driver = BaseDriver.get_driver(browser_type, headless)
    driver.implicitly_wait(10)
    
    yield driver
    
    log.info("关闭浏览器")
    driver.quit()


@pytest.fixture
def test_data():
    """
    测试数据夹具
    提供测试用例所需的数据
    """
    data = ReadJson()
    return data.read_json()


@pytest.fixture
def common_fixture(browser):
    """
    通用测试夹具
    提供常用的测试操作
    """
    def navigate_to(url):
        """
        导航到指定URL
        :param url: 要访问的URL
        """
        log.info(f"导航到URL: {url}")
        browser.get(url)
        browser.maximize_window()
    
    def get_driver():
        """
        获取当前驱动实例
        :return: WebDriver实例
        """
        return browser
    
    return {
        "navigate_to": navigate_to,
        "driver": get_driver
    }


@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
    """
    Pytest钩子函数，用于生成测试报告
    捕获测试用例的执行状态，用于失败截图等操作
    """
    outcome = yield
    report = outcome.get_result()
    
    # 如果是测试函数且执行失败
    if report.when == "call" and report.failed:
        # 获取driver实例以便截图
        for fixture_name in item.fixturenames:
            if fixture_name == "browser":
                driver = item.funcargs[fixture_name]
                if driver:
                    # 保存截图
                    screenshot_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), "screenshots")
                    if not os.path.exists(screenshot_dir):
                        os.makedirs(screenshot_dir)
                    
                    screenshot_path = os.path.join(
                        screenshot_dir, 
                        f"{item.nodeid.replace('/', '_').replace(':', '_')}_failure.png"
                    )
                    driver.save_screenshot(screenshot_path)
                    log.info(f"测试失败，截图保存至: {screenshot_path}")
                    break

